package com.lyl.xxx.modules.framework.security.service.impl;

import cn.hutool.core.text.CharSequenceUtil;
import cn.hutool.core.text.StrPool;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.json.JSONUtil;
import com.lyl.xxx.common.constants.Constants;
import com.lyl.xxx.common.constants.RedisConstant;
import com.lyl.xxx.common.utils.RedisUtil;
import com.lyl.xxx.modules.framework.security.config.properties.SecurityProperties;
import com.lyl.xxx.modules.framework.security.model.details.LoginDetails;
import com.lyl.xxx.modules.framework.security.service.TokenService;
import com.lyl.xxx.modules.framework.security.utils.JwtUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletRequest;
import java.util.concurrent.TimeUnit;

/**
 * @author Mr.Luo
 * @date 2022-09-19 11:53
 * @desc
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class TokenServiceImpl implements TokenService {
    private final SecurityProperties securityProperties;

    @Override
    public String refreshToken(LoginDetails loginDetails) {
        long loginTime = System.currentTimeMillis();
        long expireTime = loginTime + securityProperties.getToken().getExpireTime() * Constants.ONE_MINUTE;
        loginDetails.setLoginTime(loginTime)
                .setExpireTime(expireTime)
                .setToken(CharSequenceUtil.blankToDefault(loginDetails.getToken(), IdUtil.fastUUID()));
        //设置redis
        RedisUtil.set(RedisConstant.LOGIN_TOKEN + loginDetails.getToken(), loginDetails, securityProperties.getToken().getExpireTime(), TimeUnit.MINUTES);
        return JwtUtil.createToken(loginDetails.getToken());
    }

    @Override
    public LoginDetails getLoginDetails(HttpServletRequest request) {
        String token = getToken(request);
        if (CharSequenceUtil.isNotBlank(token)) {
            //1. 验证token
            String tokenKey = JwtUtil.parseToken(token);
            //2. 获取redis中用户信息
            Object obj = RedisUtil.get(RedisConstant.LOGIN_TOKEN + tokenKey);
            if (ObjectUtil.isNotEmpty(obj)) {
                return JSONUtil.toBean(JSONUtil.toJsonStr(obj), LoginDetails.class);
            }
        }
        return null;
    }

    @Override
    public void verifyToken(LoginDetails loginDetails) {
        long expireTime = loginDetails.getExpireTime();
        long currentTime = System.currentTimeMillis();
        if (expireTime - currentTime <= securityProperties.getToken().getMaxAutoRefreshTokenTime()) {
            refreshToken(loginDetails);
        }
    }

    private String getToken(HttpServletRequest request) {
        String token = request.getHeader(securityProperties.getToken().getHeaderName());
        if (CharSequenceUtil.isNotBlank(token) && token.startsWith(securityProperties.getToken().getPrefix() + StrPool.C_SPACE)) {
            token = token.replace(securityProperties.getToken().getPrefix() + StrPool.C_SPACE, "");
        }
        return token;
    }
}
